package com.eva.job;

import com.eva.job.constants.JobConstants;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.SuperBuilder;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 任务调度器代理
 */
@Slf4j
@Component
public class SchedulerProxy {

    @Resource
    private Scheduler scheduler;

    /**
     * 创建并将定时任务加入调度
     *
     * @param job 详见SchedulerProxy$Job
     */
    public void createAndScheduleCronJob(CronJob job) {
        try {
            // 创建Job
            Class<? extends Job> handleClass = JobHandler.class;
            // - 如果禁用并发，则采用JobHandlerWithDisallowConcurrent类实现
            if (job.getDisallowConcurrent()) {
                handleClass = JobHandlerWithDisallowConcurrent.class;
            }
            JobDetail newJob = JobBuilder.newJob(handleClass).withIdentity(job.getHandler()).build();
            // - 添加JOB运行时数据
            newJob.getJobDataMap().put(JobConstants.DATA_MAP_JOB_ID, job.getId());

            // 创建Trigger
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(job.getHandler() + "Trigger")
                    .withSchedule(scheduleBuilder).build();

            // 加入调度
            scheduler.scheduleJob(newJob, trigger);
        } catch (SchedulerException e) {
            log.error("创建定时任务出现了异常！", e);
        }
    }

    /**
     * 删除定时任务
     *
     * @param identity 定时任务ID
     */
    public void deleteJob (String identity) {
        try {
            scheduler.deleteJob(JobKey.jobKey(identity));
        } catch (SchedulerException e) {
            log.error("删除定时任务出现了异常！", e);
        }
    }

    /**
     * JOB代理对象
     */
    @Data
    @SuperBuilder
    public static class CronJob {

        @ApiModelProperty("任务ID")
        private Integer id;

        @ApiModelProperty("处理器类名称")
        private String handler;

        @ApiModelProperty("CRON表达式")
        private String cronExpression;

        @ApiModelProperty("是否禁用并发执行")
        private Boolean disallowConcurrent;
    }
}
